/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.task.event;

import cn.easyplatform.EasyPlatformWithLabelKeyException;
import cn.easyplatform.lang.Files;
import cn.easyplatform.lang.Lang;
import cn.easyplatform.lang.Nums;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.request.*;
import cn.easyplatform.messages.response.SimpleResponseMessage;
import cn.easyplatform.messages.vos.*;
import cn.easyplatform.messages.vos.datalist.*;
import cn.easyplatform.spi.service.ApplicationService;
import cn.easyplatform.spi.service.ListService;
import cn.easyplatform.spi.service.TaskService;
import cn.easyplatform.type.Constants;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.type.ListRowVo;
import cn.easyplatform.type.UserType;
import cn.easyplatform.utils.JmsUtils;
import cn.easyplatform.web.WebApps;
import cn.easyplatform.web.contexts.Contexts;
import cn.easyplatform.web.controller.LayoutController;
import cn.easyplatform.web.dialog.ActionEvent;
import cn.easyplatform.web.dialog.MessageBox;
import cn.easyplatform.web.dialog.SourceViewDlg;
import cn.easyplatform.web.exporter.excel.ExcelExporter;
import cn.easyplatform.web.exporter.pdf.PdfExporter;
import cn.easyplatform.web.layout.IMainTaskBuilder;
import cn.easyplatform.web.layout.LayoutManagerFactory;
import cn.easyplatform.web.listener.LogoutListener;
import cn.easyplatform.web.message.entity.Destination;
import cn.easyplatform.web.service.ServiceLocator;
import cn.easyplatform.web.task.*;
import cn.easyplatform.web.task.support.ManagedComponent;
import cn.easyplatform.web.task.support.ManagedComponents;
import cn.easyplatform.web.task.support.scripting.EventExitException;
import cn.easyplatform.web.task.support.scripting.UtilsCmd;
import cn.easyplatform.web.task.zkex.ExportSupport;
import cn.easyplatform.web.task.zkex.ListSupport;
import cn.easyplatform.web.task.zkex.list.OperableListSupport;
import cn.easyplatform.web.task.zkex.list.PanelSupport;
import cn.easyplatform.web.task.zkex.list.exporter.AbstractExporter;
import cn.easyplatform.web.utils.*;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.zkoss.lang.Objects;
import org.zkoss.util.media.AMedia;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.ext.Disable;
import org.zkoss.zk.ui.ext.Readonly;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zkmax.zul.Filedownload;
import org.zkoss.zul.*;
import org.zkoss.zul.event.PagingEvent;
import org.zkoss.zul.impl.MeshElement;

import javax.jms.*;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.*;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class EventDispatcher extends UtilsCmd {

    private EventListenerHandler elh;

    private String id;

    private int actionFlag = 0;

    private Event sourceEvent;

    public EventDispatcher(EventSupport handler, Map<String, Object> scope,
                           EventListenerHandler elh, Event sourceEvent) {
        super(handler, scope);
        this.elh = elh;
        this.id = handler.getId();
        this.sourceEvent = sourceEvent;
    }

    public EventDispatcher(EventListenerHandler elh, Map<String, Object> scope,
                           Event sourceEvent) {
        this(null, scope, elh, sourceEvent);
    }

    public void copy() {
        if (actionFlag < 0)
            throw new EventExitException();
        if (handler instanceof OperableHandler)
            ((OperableHandler) handler).copy(new EventEntry<String>(
                    actionFlag, id));
    }

    public void create() {
        if (actionFlag < 0)
            throw new EventExitException();
        if (handler instanceof OperableHandler)
            ((OperableHandler) handler).create(new EventEntry<String>(
                    actionFlag, id));
    }

    public void read() {
        if (actionFlag < 0)
            throw new EventExitException();
        if (handler instanceof OperableListSupport) {
            ((OperableListSupport) handler).read(new EventEntry<String>(
                    actionFlag, id));
        }
    }

    public void edit() {
        if (actionFlag < 0)
            throw new EventExitException();
        if (handler instanceof OperableHandler)
            ((OperableHandler) handler).edit(new EventEntry<String>(
                    actionFlag, id));
    }

    public void remove() {
        if (actionFlag < 0)
            throw new EventExitException();
        if (handler instanceof OperableHandler)
            ((OperableHandler) handler).delete(new EventEntry<String>(
                    actionFlag, id));
    }

    public void commit() {
        if (handler instanceof OperableHandler)
            ((OperableHandler) handler).save(new EventEntry<Boolean>(
                    actionFlag, true));
        if (actionFlag < 0)
            throw new EventExitException();
    }

    public void save() {
        if (handler instanceof OperableHandler)
            ((OperableHandler) handler).save(new EventEntry<Boolean>(
                    actionFlag, false));
        if (actionFlag < 0)
            throw new EventExitException();
    }

    public void subscribe(String topic) {
        if (handler instanceof MainTaskSupport)
            ((MainTaskSupport) handler).subscribe(topic);
        else if (handler instanceof ListSupport
                || handler instanceof PanelSupport) {
            MainTaskSupport task = (MainTaskSupport) ((OperableHandler) handler)
                    .getParent();
            task.subscribe(topic);
        }
    }

    public void unsubscribe() {
        if (handler instanceof MainTaskSupport)
            ((MainTaskSupport) handler).unsubscribe();
        else if (handler instanceof ListSupport
                || handler instanceof PanelSupport) {
            MainTaskSupport task = (MainTaskSupport) ((OperableHandler) handler)
                    .getParent();
            task.unsubscribe();
        }
    }

    public void next(String code) {
        if (handler instanceof MainTaskSupport) {
            MainTaskSupport task = (MainTaskSupport) handler;
            NextVo vo = new NextVo(code);
            EventEntry<NextVo> entry = new EventEntry<NextVo>(actionFlag, vo);
            task.next(entry);
        } else if (handler instanceof ListSupport) {
            ListNextVo params = null;
            ListSupport dls = (ListSupport) handler;
            ListRowVo rv = dls.getSelectedValue();
            if (rv != null)
                params = new ListNextVo(code, dls.getComponent().getId(),
                        dls.isCustom() ? rv.getData() : rv.getKeys());
            else if (code != null && !code.equalsIgnoreCase("C"))
                throw new EasyPlatformWithLabelKeyException(
                        "datalist.selected.empty", dls.getComponent().getId());
            else
                params = new ListNextVo(code, dls.getComponent().getId(), null);
            MainTaskSupport task = (MainTaskSupport) ((OperableHandler) handler)
                    .getParent();
            task.next(new EventEntry<NextVo>(actionFlag, params));
        }
        if (actionFlag < 0)
            throw new EventExitException();
    }

    public void prev() {
        if (handler instanceof MainTaskSupport) {
            MainTaskSupport task = (MainTaskSupport) handler;
            task.prev(actionFlag);
        } else if (handler instanceof ListSupport
                || handler instanceof PanelSupport) {
            MainTaskSupport task = (MainTaskSupport) ((OperableHandler) handler)
                    .getParent();
            task.prev(actionFlag);
        }
        if (actionFlag < 0)
            throw new EventExitException();
    }

    public void reset() {
        if (actionFlag < 0)
            throw new EventExitException();
        if (handler instanceof OperableListSupport)
            ((OperableListSupport) handler).reset(false);
        else if (handler instanceof PanelSupport)
            ((PanelSupport) handler).reset();
        else if (handler instanceof MainTaskSupport) {
            ((MainTaskSupport) handler).create(new EventEntry<String>(
                    actionFlag, id));
            if (actionFlag == 0)
                ((OperableHandler) handler).reload();
        }
    }

    public void reload(String... comps) {
        if (actionFlag < 0)
            throw new EventExitException();
        handler.reload(comps);
    }

    public void refresh(String... comps) {
        if (handler instanceof OperableHandler) {
            ((OperableHandler) handler).refresh(new EventEntry<FieldEntry>(
                    actionFlag, new FieldEntry(comps, false)));
            if (actionFlag < 0)
                throw new EventExitException();
        }
    }

    public void update(String... comps) {
        if (handler instanceof OperableHandler)
            ((OperableHandler) handler).update(comps);
    }

    public void print() {
        if (handler instanceof OperableHandler)
            ExtUtils.print(((OperableHandler) handler).getComponent(), null,
                    null);
    }

    public void print(String compId, String uri, String cssuri) {
        if (handler instanceof OperableHandler) {
            Component comp = null;
            if (compId == null)
                comp = ((OperableHandler) handler).getComponent();
            else
                comp = ((OperableHandler) handler).getComponent()
                        .getFellowIfAny(compId);
            if (comp != null)
                ExtUtils.print(comp, uri, cssuri);
        }
    }

    public void close() {
        if (actionFlag < 0)
            throw new EventExitException();
        if (handler instanceof MainTaskSupport)
            ((MainTaskSupport) handler).close(false);
        else if (((OperableHandler) handler).getParent() instanceof MainTaskSupport)
            ((MainTaskSupport) ((OperableHandler) handler).getParent())
                    .close(false);
        else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            ((MainTaskSupport) ((OperableHandler) ps).getParent()).close(false);
        }
    }

    public void go(Object... args) {
        // go(taskId,openModel,code|cid,code);
        // openModel == OPEN_EMMBED时第3个参数是容器的id,
        // 否则如果长度大于1表示弹出窗口的位置,参考window.setPosition方法
        String taskId = (String) args[0];
        int openModel = Constants.OPEN_MODAL;
        String code = null;
        // 强制运行唯一功能
        boolean unique = false;
        LoginVo currentUser = Contexts.getUser();
        if (args.length > 1) {
            if (args[1] instanceof Boolean)
                unique = (Boolean) args[1];
            else
                openModel = Nums.toInt(args[1], Constants.OPEN_MODAL);
        } else if (currentUser.getType() >= UserType.TYPE_OAUTH)
            openModel = Constants.OPEN_NEW_PAGE;
        else
            openModel = Constants.OPEN_MODAL;
        if (openModel == Constants.OPEN_NEW_PAGE) {//跳转页面
            Executions.getCurrent().sendRedirect("/page.go?app=" + Contexts.getEnv().getProjectId() + "&tid=" + taskId, "_blank");
            return;
        }
        String cid = null;
        if (args.length > 2) {
            if (args[2] instanceof String) {
                cid = (String) args[2];
                if (cid.length() == 1) {
                    code = cid;
                    cid = null;
                }
            } else if (args[2] instanceof Boolean)
                unique = (Boolean) args[2];
        }
        if (args.length > 3) {
            if (args[3] instanceof String)
                code = (String) args[3];
            else if (args[3] instanceof Boolean)
                unique = (Boolean) args[3];
        }
        if (args.length > 4 && args[4] instanceof Boolean)
            unique = (Boolean) args[4];
        Component container = null;
        if (openModel == Constants.OPEN_EMBBED && cid != null) {
            container = ((OperableHandler) handler).getComponent()
                    .getFellowIfAny(cid);
            if (container == null)
                openModel = Constants.OPEN_MODAL;
        } else if (openModel == Constants.OPEN_NORMAL)
            container = sourceEvent.getTarget().getPage().getFellowIfAny("gv5container");

        if (container == null) {
            if (openModel == Constants.OPEN_MODAL || handler == null) {
                container = sourceEvent.getTarget();
                openModel = Constants.OPEN_MODAL;
            } else {
                if (handler instanceof OperableHandler)
                    container = ((OperableHandler) handler).getContainer();
                else if (handler instanceof ManagedComponents)
                    container = ((ManagedComponents) handler).getParent().getContainer();
                if (openModel == Constants.OPEN_NORMAL && currentUser.getType() >= UserType.TYPE_OAUTH) {
                    List<String> ids = (List<String>) container.getDesktop().removeAttribute(Contexts.ANONYMOUS_TASKS);
                    if (ids != null) {
                        TaskService tcs = ServiceLocator.lookup(
                                TaskService.class);
                        for (String id : ids)
                            tcs.close(new SimpleRequestMessage(id, null));
                    }
                    Executions.getCurrent().sendRedirect("/page.go?app=" + Contexts.getEnv().getProjectId() + "&tid=" + taskId);
                    return;
                }
            }
        }
        TaskInfo taskInfo = new TaskInfo(taskId);
        taskInfo.setName(PageUtils.getComponentLabel(sourceEvent.getTarget()));
        TaskVo tv = null;
        if (handler instanceof ListSupport || handler instanceof PanelSupport) {
            ListSupport dls = null;
            if (handler instanceof ListSupport)
                dls = (ListSupport) handler;
            else
                dls = ((PanelSupport) handler).getList();
            tv = new ListTaskVo(taskId);
            ((ListTaskVo) tv).setListId(dls.getComponent().getId());
            if (dls.getSelectedValue() != null) {
                ListRowVo rv = dls.getSelectedValue();
                ((ListTaskVo) tv).setKeys(dls.isCustom() ? rv.getData() : rv
                        .getKeys());
                taskInfo.setListId(dls.getComponent().getId());
                taskInfo.setKeys(dls.isCustom() ? rv.getData() : rv.getKeys());
                // if (!dls.isCustom() && code == null)
                // code = "U";
            }
        } else
            tv = new TaskVo(taskId);
        // 只有打开方式不是EMBBED的功能
        if ((openModel != Constants.OPEN_EMBBED && openModel < 10) || unique) {
            int c = WebUtils.checkTask(taskInfo, container);
            if (c == 1 || c == 0) {// 已经在运行
                if (c == 1)
                    throw new EasyPlatformWithLabelKeyException(
                            "main.task.has.run", taskId);
                return;
            }
        }
        if (openModel == Constants.OPEN_EMBBED)
            tv.setCid(cid);
        tv.setOpenModel(openModel);
        if (code != null)
            tv.setProcessCode(code);
        if (tv.getCid() == null && scope.get("$easyplatform") instanceof LayoutController) {
            LayoutController layout = (LayoutController) scope.get("$easyplatform");
            layout.go(tv, handler);
        } else {
            TaskService mtc = ServiceLocator
                    .lookup(TaskService.class);
            BeginRequestMessage req = new BeginRequestMessage(tv);
            if (actionFlag != 0) {
                req.setId(id);
                req.setActionFlag(actionFlag);
            } else if (handler != null)
                req.setId(handler.getId());
            IResponseMessage<?> resp = mtc.begin(req);
            if (resp.isSuccess()) {
                if (resp.getBody() != null
                        && resp.getBody() instanceof AbstractPageVo) {
                    MainTaskSupport builder = null;
                    try {
                        AbstractPageVo pv = (AbstractPageVo) resp.getBody();
                        if (pv instanceof PageVo)
                            ((PageVo) pv).setPosition(cid);
                        builder = (MainTaskSupport) LayoutManagerFactory
                                .createLayoutManager()
                                .getMainTaskBuilder(container,
                                        tv.getId(), pv);
                        ((IMainTaskBuilder) builder).build();
                        taskInfo.setId(pv.getId());
                        taskInfo.setTitle(pv.getTitile());
                        taskInfo.setImage(pv.getImage());
                        if (openModel == Constants.OPEN_EMBBED) {
                            MainTaskSupport ts = null;
                            if (handler instanceof ListSupport
                                    || handler instanceof PanelSupport)
                                ts = ((MainTaskSupport) ((OperableHandler) handler)
                                        .getParent());
                            else
                                ts = ((MainTaskSupport) handler);
                            ts.appendChild(cid, builder);
                            taskInfo.setParentId(handler.getId());
                        } else if (handler != null) {
                            if (handler instanceof PanelSupport) {
                                ListSupport ls = ((PanelSupport) handler).getList();
                                if (ls instanceof OperableHandler)
                                    ((IMainTaskBuilder) builder).setHost((OperableHandler) ls);
                                else
                                    ((IMainTaskBuilder) builder).setHost(ls.getMainHandler());
                            } else if (handler instanceof OperableHandler)
                                ((IMainTaskBuilder) builder).setHost((OperableHandler) handler);
                        }
                        WebUtils.registryTask(taskInfo);
                        WebUtils.setAnonymousInfo(container.getDesktop(), pv.getId());
                    } catch (EasyPlatformWithLabelKeyException ex) {
                        builder.close(false);
                        throw ex;
                    } catch (BackendException ex) {
                        builder.close(false);
                        throw ex;
                    } catch (Exception ex) {
                        builder.close(false);
                        throw Lang.wrapThrow(ex);
                    }
                }
            } else {
                if (openModel == Constants.OPEN_EMBBED && container != null)
                    container.getChildren().clear();
                throw new BackendException(resp);
            }
        }
    }

    public Object evalExpression(String expr, int type, Component... args) {
        if (actionFlag == 0)
            return super.evalExpression(expr, type, args);
        else if (actionFlag == -1) {
            if ("eval".equals(breakMethod)) {
                breakMethod = null;
                elh.setActionFlag(0, handler.getId());
                super.evalExpression(expr, type, -1, args);
            }
            throw new EventExitException();
        } else {
            if ("eval".equals(breakMethod)) {
                breakMethod = null;
                elh.setActionFlag(0, handler.getId());
                return super.evalExpression(expr, type, 1, args);
            } else {
                elh.setActionFlag(0, handler.getId());
                return null;
            }
        }
    }

    public void download(Object... args) {
        if (args.length == 0)
            return;
        Object src = args[0];
        String contentType = null;
        if (args.length > 1)
            contentType = (String) args[1];
        if (src instanceof String) {
            String fn = (String) src;
            Filedownload.save(WebUtils.getFileContent(fn), contentType, FilenameUtils.getName(fn));
        } else if (src instanceof byte[]) {
            byte[] content = (byte[]) src;
            String flnm = null;
            if (args.length > 2)
                flnm = (String) args[2];
            else
                flnm = RandomStringUtils.random(10, true, false);
            Filedownload.save(content, contentType, flnm);
        }
    }


    public void multipleDownload(Object... args) {
        if (args.length == 0)
            return;
        Files.createDirIfNoExists("FileTempFolder");
        //删除执行在下载前，故只能由下一次删除上一次的文件
        FileUtil.delAllFile("FileTempFolder");
        String folderName = "FileTempFolder" + File.separator + Labels.getLabel("event.batch.export") + System.currentTimeMillis();
        File folder = Files.createDirIfNoExists(folderName);
        for (int i = 0; i < args.length; i++) {
            Files.write(folderName + File.separator + FilenameUtils.getName((String) args[i]), WebUtils.getFileContent((String) args[i]));
        }
        File target = new File(folderName + ".zip");
        FileUtil.compress(folder, target, false);
        try {
            Filedownload.save(target, null);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    /**
     * 清除所有数据
     */
    public void clear() {
        if (actionFlag < 0)
            throw new EventExitException();
        if (handler instanceof OperableListSupport) {
            ListSupport ls = (ListSupport) handler;
            ListService ds = ServiceLocator
                    .lookup(ListService.class);
            IResponseMessage<?> resp = ds.doClear(new SimpleTextRequestMessage(
                    ls.getMainHandler().getId(), ls.getComponent().getId()));
            if (resp.isSuccess())
                ls.clear();
            else
                throw new BackendException(resp);
        } else if (handler instanceof PanelSupport) {
            ListSupport ls = ((PanelSupport) handler).getList();
            if (ls instanceof OperableListSupport) {
                ListService ds = ServiceLocator
                        .lookup(ListService.class);
                IResponseMessage<?> resp = ds
                        .doClear(new SimpleTextRequestMessage(ls
                                .getMainHandler().getId(), ls.getComponent()
                                .getId()));
                if (resp.isSuccess())
                    ls.clear();
                else
                    throw new BackendException(resp);
            } else
                ls.clear();
        } else if (handler instanceof ListSupport)
            ((ListSupport) handler).clear();
    }

    /**
     * 分页
     */
    public void paging(int pge) {
        if (sourceEvent instanceof PagingEvent) {
            PagingEvent pe = (PagingEvent) sourceEvent;
            if (handler instanceof ListSupport)
                ((ListSupport) handler).paging(pe.getActivePage() + pge);
            else if (handler instanceof PanelSupport)
                ((PanelSupport) handler).getList().paging(
                        pe.getActivePage() + pge);
        }
    }

    /**
     * 查询
     */
    public void query() {
        if (handler instanceof ListSupport)
            ((ListSupport) handler).query(null);
        else if (handler instanceof PanelSupport)
            ((PanelSupport) handler).getList().query(null);
    }

    /**
     * 根据列名称排序
     *
     * @param name
     * @param isAscending
     */
    public void sort(String name, boolean isAscending) {
        if (handler instanceof ListSupport)
            ((ListSupport) handler).sort(name, isAscending);
        else if (handler instanceof PanelSupport)
            ((PanelSupport) handler).getList().sort(name, isAscending);

    }

    /**
     * 导出
     */
    public void export() {
        if (actionFlag < 0)
            throw new EventExitException();
        if (handler instanceof ListSupport) {
            ListSupport ls = (ListSupport) handler;
            AbstractExporter.createExporter(ls.getMainHandler(), ls).doExport();
        } else if (handler instanceof PanelSupport) {
            ListSupport ls = ((PanelSupport) handler).getList();
            AbstractExporter.createExporter(ls.getMainHandler(), ls).doExport();
        }
    }

    /**
     * 批量处理
     *
     * @param code
     */
    public void batch(String code) {
        if (actionFlag < 0)
            throw new EventExitException();
        if (handler instanceof PanelSupport) {
            PanelSupport ps = (PanelSupport) handler;
            if (ps.getList() instanceof OperableListSupport) {
                OperableListSupport op = (OperableListSupport) handler;
                List<Object[]> items = op.getKeys(true);
                if (items.isEmpty()) {
                    throw new EasyPlatformWithLabelKeyException(
                            "datalist.selected.empty", op.getName());
                } else {
                    if (code == null)
                        code = ((OperableHandler) handler).getProcessCode();
                    ListBatchVo bo = new ListBatchVo(op.getComponent().getId(),
                            items, code);
                    MainTaskSupport task = (MainTaskSupport) ((OperableHandler) handler)
                            .getParent();
                    task.batch(bo);
                }
            }
        } else if (handler instanceof OperableListSupport) {
            OperableListSupport op = (OperableListSupport) handler;
            List<Object[]> items = op.getKeys(true);
            if (items.isEmpty()) {
                throw new EasyPlatformWithLabelKeyException(
                        "datalist.selected.empty", op.getName());
            } else {
                if (code == null)
                    code = ((OperableHandler) handler).getProcessCode();
                ListBatchVo bo = new ListBatchVo(op.getComponent().getId(),
                        items, code);
                MainTaskSupport task = (MainTaskSupport) ((OperableHandler) handler)
                        .getParent();
                task.batch(bo);
            }
        }
    }

    /**
     * 对列表的记录进行操作
     *
     * @param args
     */
    @SuppressWarnings("unchecked")
    public void evalList(String[] args) {
        if (args.length < 2) {
            Clients.wrongValue(sourceEvent.getTarget(), Labels.getLabel(
                    "page.eval.invalid",
                    new String[]{"evalList()",
                            Labels.getLabel("page.eval.args.invalid")}));
            return;
        }
        String target = null;
        String logic = null;
        String source = null;
        if (args.length == 2) {
            target = args[0];
            logic = args[1];
        } else if (args.length == 3) {
            target = args[0];
            source = args[1];
            logic = args[2];
        }
        if (Strings.isBlank(logic)) {
            Clients.wrongValue(
                    sourceEvent.getTarget(),
                    Labels.getLabel("page.eval.invalid", new String[]{
                            "evalList()", "Logic is not empty"}));
            return;
        }
        OperableHandler task = (OperableHandler) handler;
        if (handler instanceof OperableListSupport) {
            OperableListSupport op = (OperableListSupport) handler;
            task = op.getMainHandler();
        } else if (handler instanceof PanelSupport) {
            task = ((PanelSupport) handler).getParent();
        }
        if (task instanceof MainTaskSupport) {
            ManagedComponent mc = ((MainTaskSupport) task)
                    .getManagedEntityComponent(target);
            if (mc == null || !(mc instanceof OperableListSupport)) {
                Clients.wrongValue(
                        sourceEvent.getTarget(),
                        "eval(source,target,logic):"
                                + Labels.getLabel("move.btn.source.not.found",
                                new String[]{target}));
                return;
            }
            OperableListSupport targetList = (OperableListSupport) mc;
            List<Object[]> targetKeys = targetList.getKeys(true);
            if (targetKeys.isEmpty()) {
                Clients.wrongValue(sourceEvent.getTarget(), Labels.getLabel(
                        "datalist.selected.empty", new String[]{target}));
                return;
            }
            ListEvalVo vo = new ListEvalVo(target, logic, targetKeys);
            OperableListSupport sourceList = null;
            if (!Strings.isBlank(source)) {
                mc = ((MainTaskSupport) task).getManagedEntityComponent(source);
                if (mc == null || !(mc instanceof OperableListSupport)) {
                    Clients.wrongValue(
                            sourceEvent.getTarget(),
                            "eval(source,target,logic):"
                                    + Labels.getLabel(
                                    "move.btn.source.not.found",
                                    new String[]{source}));
                    return;
                }
                sourceList = (OperableListSupport) mc;
                List<Object[]> sourceKeys = sourceList.getKeys(true);
                if (sourceKeys.isEmpty()) {
                    Clients.wrongValue(sourceEvent.getTarget(), Labels
                            .getLabel("datalist.selected.empty",
                                    new String[]{source}));
                    return;
                }
                vo.setSourceId(source);
                vo.setSourceKeys(sourceKeys);
            }
            ListService dls = ServiceLocator
                    .lookup(ListService.class);
            IResponseMessage<?> resp = dls.evalList(new ListEvalRequestMessage(
                    id, vo));
            if (!resp.isSuccess())
                throw new BackendException(resp);
            if (sourceList == null) {
                List<ListUpdatableRowVo> data = (List<ListUpdatableRowVo>) resp
                        .getBody();
                for (ListUpdatableRowVo row : data)
                    targetList.update(row);
            } else {
                Object[] data = (Object[]) resp.getBody();
                List<ListUpdatableRowVo> targets = (List<ListUpdatableRowVo>) data[0];
                for (ListUpdatableRowVo row : targets)
                    targetList.update(row);
                List<ListUpdatableRowVo> sources = (List<ListUpdatableRowVo>) data[1];
                for (ListUpdatableRowVo row : sources)
                    sourceList.update(row);
            }
        }
    }

    public Object getItemData(Component item, String name) {
        if (null == item
                || (!(item instanceof Listitem) && !(item instanceof Treeitem)))
            throw new EasyPlatformWithLabelKeyException("page.eval.invalid",
                    "getData", item);
        ListRowVo rv = null;
        if (item instanceof Listitem)
            rv = ((Listitem) item).getValue();
        else
            rv = ((Treeitem) item).getValue();
        if (rv != null) {
            ListSupport op = null;
            if (handler instanceof ListSupport)
                op = (ListSupport) handler;
            else if (handler instanceof PanelSupport)
                op = ((PanelSupport) handler).getList();
            if (op != null)
                return getData(op, rv.getData(), name);
        }
        return null;
    }

    /**
     * 获得选中记录某个栏位值
     *
     * @param target
     * @return
     */
    public Object getData(Object target) {
        if (target == null)
            return PageUtils.getValue(this.sourceEvent.getTarget(), false);
        if ((!(target instanceof String) && !(target instanceof Component)))
            throw new EasyPlatformWithLabelKeyException("page.eval.invalid",
                    "getData", target);
        if (target instanceof Component) {
            Component c = (Component) target;
            Object[] data = (Object[]) c.getAttribute("data");
            if (data != null) {
                Integer index = (Integer) c.getAttribute("index");
                return data[index];
            }
            return PageUtils.getValue((Component) target, false);
        }
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            Object[] data = getSelectedData();
            return getData(op, data, (String) target);
        } else if (handler instanceof PanelSupport) {
            ListSupport op = ((PanelSupport) handler).getList();
            Object[] data = getSelectedData();
            return getData(op, data, (String) target);
        } else {
            Map<String, Component> map = ((OperableHandler) handler)
                    .getManagedComponents();
            Component c = map.get(target);
            if (c != null)
                return PageUtils.getValue(c, false);
        }
        return null;
    }

    private Object getData(ListSupport op, Object[] data, String name) {
        if (data != null) {
            List<ListHeaderVo> headers = op.getHeaders();
            int index = 0;
            for (ListHeaderVo header : headers) {
                if (Objects.equals(name, header.getName()))
                    return data[op.getEntity().isShowRowNumbers() ? index - 1 : index];
                index++;
            }
        }
        return null;
    }

    public void setItemData(Component item, String name, Object value) {
        if (null == item
                || (!(item instanceof Listitem) && !(item instanceof Treeitem)))
            throw new EasyPlatformWithLabelKeyException("page.eval.invalid",
                    "setData", item);
        ListSupport op = null;
        if (handler instanceof ListSupport)
            op = (ListSupport) handler;
        else if (handler instanceof PanelSupport)
            op = ((PanelSupport) handler).getList();
        if (op != null)
            setData(op, item, name, value);
    }

    /**
     * 设置某个栏位的值
     *
     * @param target
     * @param value
     */
    public void setData(Object target, Object value) {
        setData(target, value, true);
    }

    /**
     * 设置某个栏位的值
     *
     * @param target
     * @param value
     * @param sel
     */
    public void setData(Object target, Object value, boolean sel) {
        if (target == null) {
            PageUtils.setValue(sourceEvent.getTarget(), value);
        } else {
            if ((!(target instanceof String) && !(target instanceof Component)))
                throw new EasyPlatformWithLabelKeyException(
                        "page.eval.invalid", "setData", target);
            if (handler instanceof ListSupport) {
                ListSupport op = (ListSupport) handler;
                if (target instanceof String) {
                    if (op.getComponent() instanceof Tree) {
                        Tree tree = (Tree) op.getComponent();
                        Collection<Treeitem> items = sel ? tree
                                .getSelectedItems() : tree.getItems();
                        for (Treeitem item : items) {
                            if (item.getValue() != null)
                                setData(op, item, (String) target, value);
                        }
                    } else if (op.getComponent() instanceof Listbox) {
                        Listbox listbox = (Listbox) op.getComponent();
                        Collection<Listitem> items = sel ? listbox
                                .getSelectedItems() : listbox.getItems();
                        for (Listitem item : items)
                            setData(op, item, (String) target, value);
                    }
                } else if (handler instanceof OperableListSupport) {
                    Component comp = (Component) target;
                    Map<String, Component> map = ((OperableHandler) handler)
                            .getManagedComponents();
                    int index = 0;
                    for (Component entry : map.values()) {
                        if (entry == comp)
                            break;
                        index++;
                    }
                    Object val = PageUtils.getValue(comp, false);
                    String name = op.getHeaders().get(index).getName();
                    if (!Lang.equals(value, val)) {
                        IResponseMessage<?> resp = ServiceLocator
                                .lookup(TaskService.class)
                                .setValue(
                                        new SetValueRequestMessage(id,
                                                new ListSetValueVo(name, value,
                                                        op.getComponent()
                                                                .getId(), null)));
                        if (!resp.isSuccess())
                            throw new BackendException(resp);
                        PageUtils.setValue(comp, value);
                        Event evt = new Event(Events.ON_CHANGE, comp);
                        Events.sendEvent(comp, evt);
                    }
                }
            } else if (handler instanceof PanelSupport) {
                ListSupport op = ((PanelSupport) handler).getList();
                if (target instanceof String) {// 列表记录
                    if (op.getComponent() instanceof Tree) {
                        Tree tree = (Tree) op.getComponent();
                        Collection<Treeitem> items = sel ? tree
                                .getSelectedItems() : tree.getItems();
                        for (Treeitem item : items) {
                            if (item.getValue() != null)
                                setData(op, item, (String) target, value);
                        }
                    } else if (op.getComponent() instanceof Listbox) {
                        Listbox listbox = (Listbox) op.getComponent();
                        Collection<Listitem> items = sel ? listbox
                                .getSelectedItems() : listbox.getItems();
                        for (Listitem item : items)
                            setData(op, item, (String) target, value);
                    }
                } else {
                    // 面板上的组件
                    Component comp = (Component) target;
                    Object val = PageUtils.getValue(comp, false);
                    if (!Lang.equals(value, val)) {
                        String name = (String) comp.getAttribute("id");
                        if (name == null)
                            name = comp.getId();
                        IResponseMessage<?> resp = ServiceLocator
                                .lookup(TaskService.class)
                                .setValue(
                                        new SetValueRequestMessage(id,
                                                new ListSetValueVo(name, value,
                                                        op.getComponent()
                                                                .getId(), null)));
                        if (!resp.isSuccess())
                            throw new BackendException(resp);
                        PageUtils.setValue(comp, value);
                        Event evt = new Event(Events.ON_CHANGE, comp);
                        Events.sendEvent(comp, evt);
                    }
                }
            } else {
                String name = null;
                Component comp = null;
                if (target instanceof String) {
                    name = (String) target;
                    Map<String, Component> map = ((OperableHandler) handler)
                            .getManagedComponents();
                    comp = map.get(target);
                } else {
                    comp = (Component) target;
                    name = comp.getId();
                }
                Object val = PageUtils.getValue(comp, false);
                if (!Objects.equals(value, val)) {
                    IResponseMessage<?> resp = ServiceLocator.lookup(
                            TaskService.class).setValue(
                            new SetValueRequestMessage(id, new SetValueVo(name,
                                    value)));
                    if (!resp.isSuccess())
                        throw new BackendException(resp);
                    PageUtils.setValue(comp, value);
                    Event evt = new Event(Events.ON_CHANGE, comp);
                    Events.sendEvent(comp, evt);
                }
            }
        }
    }

    protected void setData(ListSupport op, Component item, String name,
                           Object value) {
        int size = op.getHeaders().size();
        for (int i = 0; i < size; i++) {
            ListHeaderVo hv = op.getHeaders().get(i);
            if (hv.getName().equals(name)) {
                Component c = item.getChildren().get(i);
                if (c.getFirstChild() != null)
                    c = c.getFirstChild();
                if (hv.isEditable()) {
                    Object val = PageUtils.getValue(c, false);
                    if (!Lang.equals(value, val)) {
                        PageUtils.setValue(c, value);
                        Event evt = new Event(Events.ON_CHANGE, c);
                        Events.sendEvent(c, evt);
                    }
                } else if (!(c instanceof Button)) {
                    if (!Strings.isBlank(hv.getFormat()) && value != null)
                        value = WebUtils.format(hv.getFormat(), value);
                    PageUtils.setValue(c, value);
                }
                break;
            }// equals
        }// for
    }

    /**
     * 获取选中的数据
     *
     * @return
     */
    public Object[] getSelectedData() {
        Component item = getSelectedItem();
        if (item != null) {
            ListRowVo rv = null;
            if (item instanceof Listitem)
                rv = ((Listitem) item).getValue();
            else if (item instanceof Treeitem)
                rv = ((Treeitem) item).getValue();
            else if (item instanceof Row)
                rv = ((Row) item).getValue();
            if (rv != null)
                return rv.getData();
        }
        return null;
    }

    /**
     * 获取选中的数据
     *
     * @return
     */
    public Object[][] getSelectedDatas() {
        List<Object[]> data = new ArrayList<Object[]>();
        Collection<?> items = getSelectedItems();
        if (items != null) {
            for (Object item : items) {
                ListRowVo rv = null;
                if (item instanceof Listitem)
                    rv = ((Listitem) item).getValue();
                else
                    rv = ((Treeitem) item).getValue();
                if (rv != null)
                    data.add(rv.getData());
            }
        }
        Object[][] objs = new Object[data.size()][];
        data.toArray(objs);
        return objs;
    }

    /**
     * @return
     */
    public RowEntry getSelectedRow() {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            Component c = op.getComponent();
            if (c instanceof Tree) {
                Treeitem ti = ((Tree) c).getSelectedItem();
                if (ti != null && ti.getValue() != null)
                    return new RowEntry(this, op, ti);
            } else {
                Listitem li = ((Listbox) c).getSelectedItem();
                return new RowEntry(this, op, li);
            }
        } else if (handler instanceof PanelSupport) {
            ListSupport op = ((PanelSupport) handler).getList();
            Component c = op.getComponent();
            if (c instanceof Tree) {
                Treeitem ti = ((Tree) c).getSelectedItem();
                if (ti != null && ti.getValue() != null)
                    return new RowEntry(this, op, ti);
            } else {
                Listitem li = ((Listbox) c).getSelectedItem();
                return new RowEntry(this, op, li);
            }
        }
        return null;
    }

    /**
     * 获取选中的数据
     *
     * @return
     */
    public RowEntry[] getSelectedRows() {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            Component c = op.getComponent();
            if (c instanceof Tree)
                return getTreeData(op, ((Tree) c).getSelectedItems());
            else
                return getListData(op, ((Listbox) c).getSelectedItems());
        } else if (handler instanceof PanelSupport) {
            ListSupport op = ((PanelSupport) handler).getList();
            Component c = op.getComponent();
            if (c instanceof Tree)
                return getTreeData(op, ((Tree) c).getSelectedItems());
            else
                return getListData(op, ((Listbox) c).getSelectedItems());
        }
        return new RowEntry[0];
    }

    /**
     * 获取所有的数据
     *
     * @return
     */
    public Object[][] getData() {
        List<Object[]> data = new ArrayList<Object[]>();
        Collection<?> items = getItems();
        for (Object item : items) {
            ListRowVo rv = null;
            if (item instanceof Listitem)
                rv = ((Listitem) item).getValue();
            else
                rv = ((Treeitem) item).getValue();
            if (rv != null)
                data.add(rv.getData());
        }
        Object[][] objs = new Object[data.size()][];
        data.toArray(objs);
        return objs;
    }

    /**
     * 获取所有的数据
     *
     * @return
     */
    public RowEntry[] getRows() {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            Component c = op.getComponent();
            if (c instanceof Tree)
                return getTreeData(op, ((Tree) c).getItems());
            else
                return getListData(op, ((Listbox) c).getItems());
        } else if (handler instanceof PanelSupport) {
            ListSupport op = ((PanelSupport) handler).getList();
            Component c = op.getComponent();
            if (c instanceof Tree)
                return getTreeData(op, ((Tree) c).getItems());
            else
                return getListData(op, ((Listbox) c).getItems());
        }
        return new RowEntry[0];
    }

    private RowEntry[] getListData(ListSupport support,
                                   Collection<Listitem> items) {
        List<RowEntry> data = new ArrayList<RowEntry>(items.size());
        for (Listitem item : items) {
            if (item.getValue() != null)
                data.add(new RowEntry(this, support, item));
        }
        RowEntry[] objs = new RowEntry[data.size()];
        data.toArray(objs);
        return objs;
    }

    private RowEntry[] getTreeData(ListSupport support,
                                   Collection<Treeitem> items) {
        List<RowEntry> data = new ArrayList<RowEntry>(items.size());
        for (Treeitem item : items) {
            if (item.getValue() != null)
                data.add(new RowEntry(this, support, item));
        }
        RowEntry[] objs = new RowEntry[data.size()];
        data.toArray(objs);
        return objs;
    }

    /**
     * 获取所有选中的记录项
     *
     * @return
     */
    public Collection<?> getSelectedItems() {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            Component c = op.getComponent();
            if (c instanceof Tree)
                return ((Tree) c).getSelectedItems();
            else
                return ((Listbox) c).getSelectedItems();
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            Component c = ps.getComponent();
            if (c instanceof Tree)
                return ((Tree) c).getSelectedItems();
            else
                return ((Listbox) c).getSelectedItems();
        }
        return null;
    }

    /**
     * 获得选中记录项
     *
     * @return
     */
    public Component getSelectedItem() {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            Component c = op.getComponent();
            if (c instanceof Tree)
                return ((Tree) c).getSelectedItem();
            if (c instanceof Listbox)
                return ((Listbox) c).getSelectedItem();

            return (Component) c.getAttribute("selectRow");
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            Component c = ps.getComponent();
            if (c instanceof Tree)
                return ((Tree) c).getSelectedItem();
            if (c instanceof Listbox)
                return ((Listbox) c).getSelectedItem();
            return (Component) c.getAttribute("selectRow");
        }
        return null;
    }

    /**
     * 获得所有记录项
     *
     * @return
     */
    public Collection<?> getItems() {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            Component c = op.getComponent();
            if (c instanceof Tree)
                return ((Tree) c).getItems();
            else
                return ((Listbox) c).getItems();
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            Component c = ps.getComponent();
            if (c instanceof Tree)
                return ((Tree) c).getItems();
            else
                return ((Listbox) c).getItems();
        }
        return null;
    }

    /**
     * 设置选择指定的项
     *
     * @param index
     */
    public void setSelectedIndex(int index) {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            Component c = op.getComponent();
            if (c instanceof Listbox)
                ((Listbox) c).setSelectedIndex(index);
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            Component c = ps.getComponent();
            if (c instanceof Listbox)
                ((Listbox) c).setSelectedIndex(index);
        }
    }

    public int getIndexOfItem(Listitem item) {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            Component c = op.getComponent();
            if (c instanceof Listbox)
                return ((Listbox) c).getIndexOfItem(item);
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            Component c = ps.getComponent();
            if (c instanceof Listbox)
                return ((Listbox) c).getIndexOfItem(item);
        }
        return -1;
    }

    public Listitem getItemAtIndex(int index) {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            Component c = op.getComponent();
            if (c instanceof Listbox)
                return ((Listbox) c).getItemAtIndex(index);
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            Component c = ps.getComponent();
            if (c instanceof Listbox)
                return ((Listbox) c).getItemAtIndex(index);
        }
        return null;
    }

    /**
     * 设置选择指定的项
     *
     * @param item
     */
    public void setSelectedItem(Component item) {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            Component c = op.getComponent();
            if (c instanceof Listbox)
                ((Listbox) c).setSelectedItem((Listitem) item);
            else
                ((Tree) c).setSelectedItem((Treeitem) item);
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            if (ps instanceof ListSupport) {
                ListSupport op = (ListSupport) ps;
                Component c = op.getComponent();
                if (c instanceof Listbox)
                    ((Listbox) c).setSelectedItem((Listitem) item);
                else
                    ((Tree) c).setSelectedItem((Treeitem) item);
            }
        }
    }

    /**
     * 选中的笔数
     *
     * @return
     */
    public int getSelectedCount() {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            if (op.getComponent() instanceof Listbox)
                return ((Listbox) op.getComponent()).getSelectedCount();
            else
                return ((Tree) op.getComponent()).getSelectedCount();
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            if (ps.getComponent() instanceof Listbox)
                return ((Listbox) ps.getComponent()).getSelectedCount();
            else
                return ((Tree) ps.getComponent()).getSelectedCount();
        }
        return 0;
    }

    /**
     * 总笔数
     *
     * @return
     */
    public int getCount() {
        if (handler instanceof ListSupport) {
            ListSupport op = (ListSupport) handler;
            if (op.getComponent() instanceof Listbox)
                return ((Listbox) op.getComponent()).getItemCount();
            else
                return ((Tree) op.getComponent()).getItemCount();
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            if (ps.getComponent() instanceof Listbox)
                return ((Listbox) ps.getComponent()).getItemCount();
            else
                return ((Tree) ps.getComponent()).getItemCount();
        }
        return 0;
    }

    /**
     * 对某个栏位进行汇总
     *
     * @param name
     * @param sel
     * @return
     */
    public double sum(String name, boolean sel) {
        if (handler instanceof ListSupport)
            return sum((ListSupport) handler, name, sel);
        else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            return sum(ps, name, sel);
        }
        return 0;
    }

    private double sum(ListSupport op, String name, boolean sel) {
        Collection<?> data = null;
        if (sel)
            data = getSelectedItems();
        else
            data = getItems();
        List<ListHeaderVo> headers = op.getHeaders();
        int size = headers.size();
        BigDecimal decimal = new BigDecimal(0);
        for (Object item : data) {
            ListRowVo rv = null;
            if (item instanceof Listitem)
                rv = ((Listitem) item).getValue();
            else
                rv = ((Treeitem) item).getValue();
            if (rv != null) {
                for (int i = 0; i < size; i++) {
                    ListHeaderVo hv = headers.get(i);
                    if (hv.getName().equals(name)) {
                        if (rv.getData()[i] == null || rv.getData()[i].toString().trim().equals("")) {
                        } else {
                            decimal = decimal.add(new BigDecimal(rv.getData()[i]
                                    .toString()));
                        }
                        break;
                    }
                }
            }
        }
        return decimal.doubleValue();
    }


    /**
     * 移除指定的项
     *
     * @param item
     */
    public void removeItem(Component item) {
        ListRowVo rv = null;
        String listId = null;
        if (item instanceof Listitem) {
            Listitem li = (Listitem) item;
            rv = li.getValue();
            listId = li.getListbox().getId();
        } else {
            Treeitem ti = (Treeitem) item;
            rv = ti.getValue();
            listId = ti.getTree().getId();
        }
        if (rv != null) {
            ListSelectetRowsVo row = new ListSelectetRowsVo(listId);
            row.appendKey(rv.getKeys() == null ? rv.getData() : rv.getKeys());
            ListService dls = ServiceLocator
                    .lookup(ListService.class);
            IResponseMessage<?> resp = dls
                    .doDelete(new ListDeleteRequestMessage(id, row));
            if (resp.isSuccess())
                item.detach();
            else
                throw new BackendException(resp);
        } else
            item.detach();
    }

    public void first() {
        if (handler instanceof OperableListSupport) {
            OperableListSupport op = (OperableListSupport) handler;
            op.first();
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            if (ps instanceof OperableListSupport) {
                OperableListSupport op = (OperableListSupport) ps;
                op.first();
            }
        }
    }

    public void last() {
        if (handler instanceof OperableListSupport) {
            OperableListSupport op = (OperableListSupport) handler;
            op.last();
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            if (ps instanceof OperableListSupport) {
                OperableListSupport op = (OperableListSupport) ps;
                op.last();
            }
        }
    }

    public void previous() {
        if (handler instanceof OperableListSupport) {
            OperableListSupport op = (OperableListSupport) handler;
            op.previous();
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            if (ps instanceof OperableListSupport) {
                OperableListSupport op = (OperableListSupport) ps;
                op.previous();
            }
        }
    }

    public void next() {
        if (handler instanceof OperableListSupport) {
            OperableListSupport op = (OperableListSupport) handler;
            op.next();
        } else if (handler instanceof PanelSupport) {
            ListSupport ps = ((PanelSupport) handler).getList();
            if (ps instanceof OperableListSupport) {
                OperableListSupport op = (OperableListSupport) ps;
                op.next();
            }
        }
    }

    public void setPageSize(int pageSize) {
        ListSupport ps = null;
        if (handler instanceof ListSupport)
            ps = (ListSupport) handler;
        else if (handler instanceof PanelSupport)
            ps = ((PanelSupport) handler).getList();
        if (ps != null) {
            if (!ps.getEntity().getType().equals(Constants.DETAIL)) {
                ListService dls = ServiceLocator
                        .lookup(ListService.class);
                IResponseMessage<?> resp = dls
                        .setPageSize(new ListPagingRequestMessage(id,
                                new ListPagingVo(ps.getComponent().getId(),
                                        pageSize)));
                if (!resp.isSuccess())
                    throw new BackendException(resp);
                ps.paging(1);
            }
            ps.setPageSize(pageSize);
        }
    }

    /**
     * @param eventName
     * @param target
     * @param data
     */
    public void postEvent(Component target, String eventName, Object data) {
        if (Strings.isBlank(eventName))
            eventName = PageUtils.getComponentDefaultEventName(target);
        Events.postEvent(eventName, target, data);
    }

    /**
     * 发送事件
     *
     * @param event
     */
    public void postEvent(Event event) {
        Events.postEvent(event);
    }

    /**
     * 显示源代码
     *
     * @param args
     */
    public void showSource(Object... args) {
        GetSourceVo gsv = new GetSourceVo();
        gsv.setSource(source(args));
        new SourceViewDlg(gsv, ((OperableHandler) handler).getComponent()
                .getPage());
    }

    public String source(Object... args) {
        String code = null;
        if (handler instanceof MainTaskSupport)
            code = ((MainTaskSupport) handler).getSourceCode();
        else if (handler instanceof ListSupport)
            code = ((MainTaskSupport) ((ListSupport) handler).getMainHandler()).getSourceCode();
        GetSourceVo gsv = new GetSourceVo();
        gsv.setType("eppage");
        if (args.length == 0 || Strings.isBlank((String) args[0]))
            gsv.setSource(code);
        else {
            String tag = (String) args[0];
            SAXReader reader = new SAXReader();
            try {
                reader.setEncoding("utf-8");
                Document doc = reader.read(new StringReader(code));
                Node ns = doc.getRootElement().selectSingleNode("//" + tag);
                if (ns == null)
                    gsv.setSource("");
                else
                    gsv.setSource(ns.asXML());
            } catch (Exception e) {
                if (log.isErrorEnabled())
                    log.error("source", e);
                gsv.setSource(Labels.getLabel("script.eval.error", new Object[]{"source", e.getMessage()}));
            }
        }
        if (args.length == 2 && (Boolean) args[1])
            new SourceViewDlg(gsv, ((OperableHandler) handler).getComponent()
                    .getPage());
        return gsv.getSource();
    }

    public Component createComponents(String page, String containerId) {
        Component container = ((ManagedComponents) handler).getManagedComponents().get(containerId);
        if (container == null)
            throw new IllegalArgumentException("Component '" + containerId + "' not found.");
        Component c = Executions.createComponentsDirectly(page, "zul", null, null);
        if (handler instanceof PageHandler)
            ((PageHandler) handler).doPage(c);
        container.getChildren().clear();
        container.appendChild(c);
        return c;
    }

    public Component insertComponents(String page, Component parent, Component ref) {
        Component c = Executions.createComponentsDirectly(page, "zul", null, null);
        if (handler instanceof PageHandler)
            ((PageHandler) handler).doPage(c);
        parent.insertBefore(c, ref);
        return c;
    }

    @Override
    public Object evalExpression(String expr, int type, int actionFlag, Component... args) {
        return super.evalExpression(expr, type, actionFlag, args);
    }

    public void showCode(String code, Object[] args) {
        if (actionFlag == 0 || (actionFlag > 0 && breakMethod != null && !"showCode".equals(breakMethod))) {
            ApplicationService ac = ServiceLocator
                    .lookup(ApplicationService.class);
            IResponseMessage<?> resp = ac.i18n(new SimpleTextRequestMessage(
                    code));
            if (resp.isSuccess()) {
                String msg = resp.getBody() == null ? "" : (String) resp
                        .getBody();
                char c = code.charAt(0);
                if (c == 'c' || c == 'w' || c == 'i')
                    breakMethod = "showCode";
                throw new BackendException(new SimpleResponseMessage(
                        code, MessageFormat.format(msg, args)));
            } else
                throw new BackendException(resp);
        } else {
            breakMethod = null;
            if (actionFlag == -1)
                throw new EventExitException();
            else
                elh.setActionFlag(0, handler.getId());
        }
    }

    // 显示对象话框
    public void showMessage(int type, Object msg) {
        if (actionFlag == 0 || (actionFlag > 0 && breakMethod != null && !"showMsg".equals(breakMethod))) {
            msg = msg == null ? "" : msg.toString();
            switch (type) {
                case 1:// confirm
                    breakMethod = "showMsg";
                    throw new BackendException(new SimpleResponseMessage(
                            "c000", msg));
                case 2:// warn
                    breakMethod = "showMsg";
                    throw new BackendException(new SimpleResponseMessage(
                            "w000", msg));
                case 3:// info
                    breakMethod = "showMsg";
                    throw new BackendException(new SimpleResponseMessage(
                            "i000", msg));
                case 4:// error
                    throw new BackendException(new SimpleResponseMessage(
                            "e000", msg));
            }
        } else {
            breakMethod = null;
            if (actionFlag == -1)
                throw new EventExitException();
            else
                elh.setActionFlag(0, handler.getId());
        }
    }

    public void showNotification(Object[] args) {
        if (args.length == 1)
            Clients.showNotification(args[0].toString());
        else if (args.length == 2) {
            if (args[1] instanceof Component)
                Clients.showNotification(args[0].toString(),
                        (Component) args[1]);
            else if (args[1] instanceof String) {
                Clients.showNotification(args[0].toString(), (String) args[1],
                        null, null, -1);
            } else
                Clients.showNotification(args[0].toString(), args[1].toString()
                        .equalsIgnoreCase("true"));
        } else if (args.length == 3) {
            if (args[1] instanceof String) {
                Component ref = sourceEvent.getTarget();
                if (args[2] instanceof Component)
                    ref = (Component) args[2];
                Clients.showNotification(args[0].toString(), (String) args[1],
                        ref, null, -1);
            } else if (args[1] instanceof Component) {
                Component ref = sourceEvent.getTarget();
                ref = (Component) args[1];
                Clients.showNotification(args[0].toString(), ref, args[2]
                        .toString().equalsIgnoreCase("true"));
            }
        }
    }

    public void showWrongValue(Component comp, String msg) {
        Clients.wrongValue(comp, msg);
    }

    public void check(String toField, String[] roles) {
        if (actionFlag == 0) {
            if (Objects.equals(toField, "undefined"))
                toField = "";
            Map<String, Object> arg = new HashMap<String, Object>();
            arg.put("id", id);
            arg.put("toField", toField);
            arg.put("roles", roles);
            Component c = Executions.createComponents("~./pages/check.zul",
                    null, arg);
            c.addEventListener("onCheckUser", new EventListener<Event>() {
                @Override
                public void onEvent(Event evt) throws Exception {
                    IResponseMessage<?> resp = (IResponseMessage<?>) evt
                            .getData();
                    if (resp.isSuccess()) {
                        Boolean success = (Boolean) resp.getBody();
                        if (success.booleanValue()) {
                            elh.onEvent(new ActionEvent(
                                    new Event(Events.ON_OK), id));
                        } else {
                            elh.line = 1;
                            MessageBox.showMessage(Labels
                                            .getLabel("message.dialog.title.error"),
                                    Labels.getLabel("user.check.error"));
                        }
                    } else {
                        elh.line = 1;
                        MessageBox.showMessage(resp);
                    }
                }
            });
            throw new PauseException();
        } else if (actionFlag == -1)
            throw new EventExitException();
    }

    /**
     * 与指定的用户交互
     *
     * @param text
     * @param user
     */
    public void chat(String text, String user) {
//        ChatService cs = (ChatService) sourceEvent.getTarget().getDesktop()
//                .getAttribute(ChatService.NAME);
//        if (cs != null)
//            cs.chat(text, user);
    }

    public String send(String name, Object data, Object[] toUsers) {
        if (WebApps.me().getConnectionFactory() != null) {
            Destination destination = WebApps.me().getJmsDestination(name);
            if (destination != null) {
                Connection connection = null;
                Session session = null;
                MessageProducer producer = null;
                try {
                    connection = WebApps.me().getConnectionFactory().createConnection();
                    session = connection.createSession(false, destination.getAcknowledge());
                    javax.jms.Destination dest = null;
                    if (destination.getName().endsWith("Topic"))
                        dest = session.createTopic(destination.getName());
                    else
                        dest = session.createQueue(destination.getName());
                    producer = session.createProducer(dest);
                    producer.setDeliveryMode(destination.getDeliveryMode());
                    producer.setDisableMessageID(destination.isDisableMessageID());
                    producer.setDisableMessageTimestamp(destination.isDisableMessageTimestamp());
                    producer.setPriority(destination.getPriority());
                    producer.setTimeToLive(destination.getTimeToLive());
                    if (toUsers.length > 0) {
                        String msgId = null;
                        for (Object toUser : toUsers) {
                            ObjectMessage message = session.createObjectMessage();
                            message.setObject((Serializable) data);
                            message.setStringProperty("userId", (String) toUser);
                            producer.send(message);
                            if (msgId == null)
                                msgId = message.getJMSMessageID();
                        }
                        return msgId;
                    } else {
                        ObjectMessage message = session.createObjectMessage();
                        message.setObject((Serializable) data);
                        producer.send(message);
                        return message.getJMSMessageID();
                    }
                } catch (JMSException e) {
                    throw new EasyPlatformWithLabelKeyException("jms.send.error", e.getMessage());
                } finally {
                    JmsUtils.close(connection, session, producer);
                }
            } else
                throw new EasyPlatformWithLabelKeyException("jms.connection.dest.nod.found", name);
        } else
            throw new EasyPlatformWithLabelKeyException("jms.connection.not.found");
    }

    /**
     * 用户退出
     */
    public void logout() {
        try {
            LogoutListener listener = new LogoutListener(Contexts.getEnv());
            listener.onEvent(sourceEvent);
        } catch (Exception ex) {
        }
    }

    public Object get$(String name) {
        OperableHandler ts = null;
        if (handler instanceof MainTaskSupport)
            ts = (OperableHandler) handler;
        else if (handler instanceof ListSupport)
            ts = ((ListSupport) handler).getMainHandler();
        else if (handler instanceof PanelSupport)
            ts = ((PanelSupport) handler).getParent();
        else
            ts = ((IMainTaskBuilder) handler).getHost();
        if (ts != null) {
            Map<String, Component> map = ts.getManagedComponents();
            return map.get(name);
        }
        return null;
    }

    /**
     * 设置
     *
     * @param name
     * @param value
     */
    public void set$(String name, Object value) {
        OperableHandler ts = null;
        if (handler instanceof MainTaskSupport)
            ts = (OperableHandler) handler;
        else if (handler instanceof ListSupport)
            ts = ((ListSupport) handler).getMainHandler();
        else if (handler instanceof PanelSupport)
            ts = ((PanelSupport) handler).getParent();
        else
            ts = ((IMainTaskBuilder) handler).getHost();
        if (ts != null) {
            Map<String, Component> map = ts.getManagedComponents();
            Component c = map.get(name);
            if (c != null)
                PageUtils.setValue(c, value);
        }
    }

    public void set0$(String name, Object value) {
        OperableHandler ts = null;
        if (handler instanceof MainTaskSupport)
            ts = (OperableHandler) handler;
        else if (handler instanceof ListSupport)
            ts = ((ListSupport) handler).getMainHandler();
        else if (handler instanceof PanelSupport)
            ts = ((PanelSupport) handler).getParent();
        else
            ts = ((IMainTaskBuilder) ts).getHost();
        if (ts != null) {
            if (ts instanceof ListSupport)
                ts = ((ListSupport) ts).getMainHandler();
            Map<String, Component> map = ts.getManagedComponents();
            Component c = map.get(name);
            if (c != null)
                PageUtils.setValue(c, value);
        }
    }

    public Object get0$(String name, Object value) {
        OperableHandler ts = null;
        if (handler instanceof MainTaskSupport)
            ts = (OperableHandler) handler;
        else if (handler instanceof ListSupport)
            ts = ((ListSupport) handler).getMainHandler();
        else if (handler instanceof PanelSupport)
            ts = ((PanelSupport) handler).getParent();
        ts = ((IMainTaskBuilder) ts).getHost();
        if (ts != null) {
            if (ts instanceof ListSupport)
                ts = ((ListSupport) ts).getMainHandler();
            Map<String, Component> map = ts.getManagedComponents();
            Component c = map.get(name);
            if (c != null)
                return PageUtils.getValue(c, false);
        }
        return null;
    }

    public Object host$() {
        OperableHandler ts = null;
        if (handler instanceof MainTaskSupport)
            ts = (OperableHandler) handler;
        else if (handler instanceof ListSupport)
            ts = ((ListSupport) handler).getMainHandler();
        else if (handler instanceof PanelSupport)
            ts = ((PanelSupport) handler).getParent();
        else
            ts = ((IMainTaskBuilder) handler).getHost();
        return new EventDispatcher(ts, scope, elh, sourceEvent);
    }

    public Object host0$() {
        OperableHandler ts = null;
        if (handler instanceof MainTaskSupport)
            ts = (OperableHandler) handler;
        else if (handler instanceof ListSupport)
            ts = ((ListSupport) handler).getMainHandler();
        else if (handler instanceof PanelSupport)
            ts = ((PanelSupport) handler).getParent();
        ts = ((IMainTaskBuilder) ts).getHost();
        if (ts instanceof ListSupport)
            ts = ((ListSupport) ts).getMainHandler();
        return new EventDispatcher(ts, scope, elh, sourceEvent);
    }

    /**
     * @param c
     * @param disabled
     */
    public void setDisabled(Component c, boolean disabled) {
        if (c instanceof Disable)
            ((Disable) c).setDisabled(disabled);
        else {
            Iterator<Component> itr = c.queryAll("*").iterator();
            while (itr.hasNext()) {
                Component comp = itr.next();
                if (comp instanceof Disable)
                    ((Disable) comp).setDisabled(disabled);
            }
        }
    }

    /**
     * @param c
     * @param readonly
     */
    public void setReadonly(Component c, boolean readonly) {
        if (c instanceof Readonly)
            ((Readonly) c).setReadonly(readonly);
        else {
            Iterator<Component> itr = c.queryAll("*").iterator();
            while (itr.hasNext()) {
                Component comp = itr.next();
                if (comp instanceof Readonly)
                    ((Readonly) comp).setReadonly(readonly);
            }
        }
    }

    /**
     * 导出列表当前记录
     *
     * @param type
     * @param exportHeaders
     */
    public void export(String type, Object... exportHeaders) {
        if (handler instanceof ExportSupport)
            ((ExportSupport) handler).export(type, exportHeaders);
    }

    /**
     * 导出列表所有记录
     *
     * @param type
     * @param exportHeaders
     */
    public void exportAll(String type, Object... exportHeaders) {
        if (handler instanceof ExportSupport)
            ((ExportSupport) handler).exportAll(type, exportHeaders);
    }

    /**
     * 直接下载组件内容
     *
     * @param component
     * @param filename
     */
    public void export(MeshElement component, String filename) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            String type = FilenameUtils.getExtension(filename);
            if (type.equalsIgnoreCase("pdf")) {
                PdfExporter exporter = new PdfExporter();
                exporter.export(component, out);
                AMedia amedia = new AMedia(filename + ".pdf", "pdf",
                        "application/pdf", out.toByteArray());
                Filedownload.save(amedia);
            } else {
                ExcelExporter exporter = new ExcelExporter();
                exporter.export(component, out);
                AMedia amedia = new AMedia(filename + ".xlsx", "xlsx",
                        "application/file", out.toByteArray());
                Filedownload.save(amedia);
            }
        } catch (Exception ex) {
            if (log.isErrorEnabled())
                log.error("export {},{}", filename, ex);
            throw new RuntimeException(ex);
        } finally {
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * 预览文件
     *
     * @param file
     */
    public void preview(String file) {
        FileUtil.preview(sourceEvent.getPage(), file);
    }

    /**
     * 获取当前事件对象
     *
     * @return
     */
    public Event getEvent() {
        return sourceEvent;
    }

    /**
     * 绑定变量,onShow方法有效
     *
     * @param name
     * @param value
     */
    public void bind(String name, Object value) {
        PageUtils.bindVariable(name, value, sourceEvent.getTarget());
    }

    // //////////////////////////////////////
    void set(int actionFlag, String id) {
        this.actionFlag = actionFlag;
        if (id != null)
            this.id = id;
    }

    void set(Event evt) {
        this.sourceEvent = evt;
    }

    public String getId() {
        return this.id;
    }

    public EventSupport getHandler() {
        return handler;
    }

    /**
     * 执行第3方注册逻辑并跳转到主页
     *
     * @param logic
     * @param comps
     */
    public void login(String logic, Component... comps) {
        Object data = evalExpression(logic, 1, comps);
        if (data instanceof AuthorizationVo) {
            EnvVo env = Contexts.getEnv();
            HttpServletRequest req = (HttpServletRequest) Executions.getCurrent().getNativeRequest();
            LoginVo vo = new LoginVo();
            vo.setIp(WebApps.getRemoteAddr(req));
            vo.setLocale(req.getLocale().toString());
            vo.setType(UserType.TYPE_SHARE);
            req.getSession().setAttribute(Contexts.PLATFORM_USER, vo);
            AuthorizationVo av = (AuthorizationVo) data;
            env.setMainPage(av.getMainPage());
            req.getSession().setAttribute(Contexts.PLATFORM_USER_AUTHORIZATION, av);
            if (scope.get("$easyplatform") instanceof LayoutController) {
                LayoutController layout = (LayoutController) scope.get("$easyplatform");
                layout.prev();
            } else {
                Executions.sendRedirect("/main.go");
            }
        } else if (data instanceof String) {
            Clients.wrongValue(sourceEvent.getTarget(), (String) data);
        }
    }

    public String toString() {
        return handler.getClass().getSimpleName() + "->" + handler.getName();
    }
}
